package com.example.myapplication.base;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
import android.view.ViewGroup;

import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;



/**
 * Fragment控制器。
 */
public class UIFragmentController {

    private final SparseArray<UIFragmentManager> mFragmentManagerMap = new SparseArray<>();
    @NonNull
    private final UIFragmentHostCallback mHost;

    /**
     * 创建新的Fragment控制器。
     *
     * @param host 宿主回调代理对象。
     */
    public UIFragmentController(@NonNull UIFragmentHostCallback host) {
        ArgUtils.checkNonNull("host", host);
        mHost = host;
    }

    /**
     * 将返回键点击事件传递给子Fragment。
     *
     * @return {@code true}表示事件已被子Fragment消费，{@code false}表示事件未被子Fragment消费。
     */
    public boolean onBackPressed() {
        final SparseArray<UIFragmentManager> fragmentManagerMap;
        synchronized (mFragmentManagerMap) {
            fragmentManagerMap = mFragmentManagerMap.clone();
        }
        boolean consumed = false;
        final int size = fragmentManagerMap.size();
        for (int i = 0; i < size; i++) {
            final UIFragmentManager fragmentManager = fragmentManagerMap.valueAt(i);
            final UIFragment fragment = fragmentManager.peekTop();
            if (fragment != null && fragment.onBackPressed()) {
                consumed = true;
            }
        }
        return consumed;
    }

    /**
     * 获取容器的Fragment管理器。
     *
     * @param containerViewId Fragment容器ID。
     * @return Fragment管理器。
     */
    @NonNull
    public UIFragmentManager getUIFragmentManager(@IdRes int containerViewId) {
        UIFragmentManager manager = mFragmentManagerMap.get(containerViewId);
        if (manager == null) {
            synchronized (mFragmentManagerMap) {
                manager = mFragmentManagerMap.get(containerViewId);
                if (manager == null) {
                    if (!(mHost.findViewById(containerViewId) instanceof ViewGroup)) {
                        throw new IllegalArgumentException("Parameter containerViewId is invalid");
                    }
                    manager = new UIFragmentManager(mHost.getContext(), containerViewId,
                            mHost.getFragmentManager());
                    mFragmentManagerMap.put(containerViewId, manager);
                }
            }
        }
        return manager;
    }

    /**
     * 恢复所有状态。
     *
     * @param state 状态数据包。
     */
    public void restoreAllState(@Nullable Parcelable state) {
        if (!(state instanceof SavedState)) {
            return;
        }
        final int[] containerViewIds = ((SavedState) state).mContainerViewIds;
        final Parcelable[] fragmentManagerStates = ((SavedState) state).mFragmentManagerStates;
        if (containerViewIds == null || fragmentManagerStates == null) {
            return;
        }
        final int size = containerViewIds.length;
        synchronized (mFragmentManagerMap) {
            for (int i = 0; i < size; i++) {
                final int containerViewId = containerViewIds[i];
                final UIFragmentManager fragmentManager = new UIFragmentManager(mHost.getContext(),
                        containerViewId, mHost.getFragmentManager());
                fragmentManager.restoreAllState(fragmentManagerStates[i]);
                mFragmentManagerMap.put(containerViewId, fragmentManager);
            }
        }
    }

    /**
     * 保存所有状态。
     *
     * @return 状态数据包。
     */
    @NonNull
    public Parcelable saveAllState() {
        return new SavedState(this);
    }

    static final class SavedState implements Parcelable {

        @Nullable
        private final int[] mContainerViewIds;
        @Nullable
        private final Parcelable[] mFragmentManagerStates;

        private SavedState(@NonNull UIFragmentController fragmentController) {
            final SparseArray<UIFragmentManager> fragmentManagerMap =
                    fragmentController.mFragmentManagerMap;
            final int size = fragmentManagerMap.size();
            mContainerViewIds = new int[size];
            mFragmentManagerStates = new Parcelable[size];
            for (int i = 0; i < size; i++) {
                mContainerViewIds[i] = fragmentManagerMap.keyAt(i);
                mFragmentManagerStates[i] = fragmentManagerMap.valueAt(i).saveAllState();
            }
        }

        private SavedState(@NonNull Parcel source) {
            mContainerViewIds = source.createIntArray();
            mFragmentManagerStates = source.createTypedArray(UIFragmentManager.SavedState.CREATOR);
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeIntArray(mContainerViewIds);
            dest.writeParcelableArray(mFragmentManagerStates, flags);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
            @Override
            public SavedState createFromParcel(Parcel source) {
                return new SavedState(source);
            }

            @Override
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };

    }

}
